package threshold

/**
 *	author:zd.zhang
 */
import (
	zimgio "wisdom_education_in_kunshan/image"
)

type TImage struct {
	*zimgio.Image
	IConvertRGBA2Gray zimgio.IConvertRGBA2Gray
}

/**
 *	<summary>灰度平局值法求阀值</summary>
 *	<param name="image">图片对象</param>
 *	<returns></returns>
 */
func (t *TImage) ByGrayAverage() uint8 {
	histGram := t.HistGram(t.IConvertRGBA2Gray)
	sum := 0
	amount := 0
	for i, g := range histGram {
		amount += g
		sum += i * g
	}
	return uint8(sum / amount)
}

/**
 *	<summary>百分比法求阈值</summary>
 *	<param name="image">图片对象</param>
 *	<param name="pTile">背景在图像中所占的面积百分比(0~100)</param>
 *	<returns></returns>
 */
func (t *TImage) ByPTile(pTile int) uint8 {
	histGram := t.HistGram(t.IConvertRGBA2Gray)
	sum := 0
	amount := 0
	for _, g := range histGram {
		amount += g
	}
	for i, g := range histGram {
		sum += g
		if sum >= amount*pTile/100 {
			return uint8(i)
		}
	}
	return 0
}

/**
 *	<summary>谷底最小值法求阈值</summary>
 *	<param name="image">图片对象</param>
 *	<returns></returns>
 */
func (t *TImage) ByValleyMin() uint8 {
	histGram := t.HistGram(t.IConvertRGBA2Gray)
	histGramC, p := dimodal(histGram)
	if p == nil || histGramC == nil {
		return 0
	}
	for i := p[0] + 1; i < p[1]-1; i++ {
		if histGramC[i] < histGramC[i-1] && histGramC[i] < histGramC[i+1] {
			return uint8(i)
		}
	}
	return 0
}

/**
 *	<summary>双峰平均值法求阈值</summary>
 *	<param name="image">图片对象</param>
 *	<returns></returns>
 */
func (t *TImage) ByValleyAverage() uint8 {
	histGram := t.HistGram(t.IConvertRGBA2Gray)
	_, p := dimodal(histGram)
	if p == nil {
		return 0
	}
	return uint8((p[0] + p[1]) / 2)
}

/**
 *	<summary>迭代最佳阈值法求阈值</summary>
 *	<param name="image">图片对象</param>
 *	<returns></returns>
 */
func (t *TImage) ByIterativeBest() uint8 {
	histGram := t.HistGram(t.IConvertRGBA2Gray)
	gMin := getMinHistGram(histGram)
	gMax := getMaxHistGram(histGram, gMin)
	if gMin == gMax {
		return gMax // 图像中只有一个颜色
	}
	if (gMin + 1) == gMax {
		return gMin // 图像中只有二个颜色
	}
	threshold := gMin
	newThreshold := (gMax + gMin) >> 1
	//////////////////////////////
	iter := 0
	sum := 0
	amount := 0
	ab := 0
	af := 0
	for threshold != newThreshold {
		threshold = newThreshold
		for i := int(gMin); i <= int(threshold); i++ { //根据阈值将图像分割成目标和背景两部分，求出两部分的平均灰度值
			sum += histGram[i] * i
			amount += histGram[i]
		}
		ab = sum / amount
		sum = 0
		amount = 0
		for i := threshold + 1; i <= gMax; i++ {
			sum += histGram[i] * int(i)
			amount += histGram[i]
		}
		af = sum / amount
		if af == 0 {
			return 0
		}
		sum = 0
		amount = 0
		newThreshold = uint8((ab + af) >> 1) //求出新的阈值
		iter++
		if iter >= 1000 {
			return 0
		}
	}
	return threshold
}

func (t *TImage) ByOSTU() uint8 {
	histGram := t.HistGram(t.IConvertRGBA2Gray)
	// Total number of pixels
	total := t.Width * t.Height
	var sum, sumB, wB, wF, threshold int
	var varMax float32
	for i, v := range histGram {
		sum += i * v
	}
	for i, v := range histGram {
		wB += v
		if wB == 0 {
			continue
		}
		wF = total - wB
		if wF == 0 {
			break
		}
		sumB += i * v
		mB := float32(sumB) / float32(wB)
		mF := float32(sum-sumB) / float32(wF)
		varBetween := float32(wB) * float32(wF) * (mB - mF) * (mB - mF)
		if varBetween > varMax {
			varMax = varBetween
			threshold = i
		}
	}
	return uint8(threshold)
}

func (i *TImage) Binaryzation(threshold uint8) *zimgio.Image {
	var gray uint8
	var cWhite uint8 = 0xFF
	var cBlack uint8 = 0
	var ic zimgio.IConvertRGBA2Gray = i.IConvertRGBA2Gray
	if ic == nil {
		ic = zimgio.SimpleConvertRGBA2Gray(0)
	}
	for x, col := range i.RGBA {
		for y, rgba := range col {
			if rgba.R != rgba.G || rgba.G != rgba.B {
				gray = ic.Convert(&rgba)
			} else {
				gray = rgba.R
			}
			if gray > threshold {
				i.RGBA[x][y].R = cWhite
				i.RGBA[x][y].G = cWhite
				i.RGBA[x][y].B = cWhite
			} else {
				i.RGBA[x][y].R = cBlack
				i.RGBA[x][y].G = cBlack
				i.RGBA[x][y].B = cBlack
			}
		}
	}
	return i.Image
}
